<script setup lang="ts">
import { computed } from "vue";
import { isEmpty, sum } from "lodash-unified";
import { storeToRefs } from "pinia";
import { WarnTriangleFilled } from "@element-plus/icons-vue";
import { ArrayUtils, NumberUtils } from "../../utils";
import { usePlanetSchematicsStore } from "../../cache";
import { useMarketStore } from "../../cache/MarketStore";
import { useCacheStore } from "../../sde/cache";
import type { UniverseType } from "../../sde/entity";
import type { UniversePlanet } from "@scvzerng/esi-163";
import type { PlanetResourceTreeItem } from "~components/tree";
import UniverseTypeIcon from "~components/universe-type/UniverseTypeIcon.vue";

const marketStore = useMarketStore();
const cacheStore = useCacheStore();
const { typePrices } = storeToRefs(marketStore);
type UniversePlanetMaterial = UniversePlanet & { type: UniverseType; material: UniverseType[] };
const props = defineProps<{
  planetSchematics: PlanetResourceTreeItem[];
  planets: UniversePlanetMaterial[];
}>();

const planetSchematicsStore = usePlanetSchematicsStore();

const isAssigned = (item: PlanetResourceTreeItem) => {
  return distributeResources.value.flatMap((p) => p.material).find((m) => m.id === item.id);
};

const leafItems = computed(() => {
  return Array.from(
    ArrayUtils.groupAccumulate(
      props.planetSchematics.filter((e) => isEmpty(e.children)),
      (e) => e.id,
      (e) => e.quantity
    ).entries()
  ).map(([id, quantity]) => {
    const planetSchematics = planetSchematicsStore.getById(id);
    return {
      id: planetSchematics.id,
      name: planetSchematics.name,
      quantity,
    } as PlanetResourceTreeItem;
  });
});

const getItemPrice = (item: PlanetResourceTreeItem) => {
  return (typePrices.value.get(item.id)!.buy_high ?? 0) * item.quantity;
};

const getPlanetMaterial = (planetId: number) => {
  return props.planets.find((planet) => planet.planet_id === planetId)?.material ?? [];
};
/**
 * 获取最低负载的星球
 */
const getLowestLoadPlanet = (planets: UniversePlanetMaterial[], resource: PlanetResourceTreeItem) => {
  const matchResourcePlanets = planets.filter((planet) => {
    const material = getPlanetMaterial(planet.planet_id)!;
    return material.find((item) => item.id === resource.id);
  });
  return matchResourcePlanets.sort((a, b) => a.material.length - b.material.length)[0];
};

const distributeResources = computed(() => {
  if (!props.planets) return [];
  const allocationPlanets: UniversePlanetMaterial[] = props.planets.map((planet) => ({
    ...planet,
    material: [],
  }));

  const sortedLeafItems = leafItems.value.slice().sort((a, b) => b.quantity - a.quantity);

  // 初步分配资源
  sortedLeafItems.forEach((basicResource) => {
    const planet = getLowestLoadPlanet(allocationPlanets, basicResource);
    const type = cacheStore.getType(basicResource.id);
    if (planet && type) {
      planet.material.push({ ...type, productQuantity: basicResource.quantity });
    }
  });

  // 平衡分配以避免星球负载过高
  const balanceLoad = () => {
    const sortedPlanets = allocationPlanets.slice().sort((a, b) => b.material.length - a.material.length);
    for (const heavyPlanet of sortedPlanets) {
      if (heavyPlanet.material.length <= 1) continue; // 如果负载轻或刚好，不需要平衡
      const needBalanceMaterial = [...heavyPlanet.material];
      while (needBalanceMaterial.length > 0) {
        const minLoad = allocationPlanets.slice().sort((a, b) => a.material.length - b.material.length)[0]
          .material.length;
        if (minLoad === heavyPlanet.material.length) {
          break;
        }
        const materialToMove = needBalanceMaterial.pop();
        if (materialToMove) {
          const targetPlanet = sortedPlanets
            .filter((p) => p.planet_id !== heavyPlanet.planet_id)
            .sort((a, b) => a.material.length - b.material.length)
            .find((p) => getPlanetMaterial(p.planet_id).some((item) => item.id === materialToMove.id));

          if (targetPlanet) {
            heavyPlanet.material = heavyPlanet.material.filter((item) => item.id !== materialToMove.id);
            targetPlanet.material.push(materialToMove);
          }
        }
      }
    }
  };

  balanceLoad();
  return allocationPlanets;
});

const totalItemPrice = computed(() => {
  return sum(leafItems.value.map(getItemPrice));
});
</script>

<template>
  <div class="space-y-2">
    <el-card>
      <template #header>
        原始资源 <el-tag type="danger">{{ NumberUtils.readableText(totalItemPrice) }} </el-tag></template
      >
      <div v-for="item in leafItems" :key="item.id" class="flex space-x-2 items-center space-y-1">
        <el-tooltip content="该资源尚未分配">
          <div :style="{ visibility: isAssigned(item) ? 'hidden' : 'visible' }">
            <el-icon color="red" :size="16">
              <WarnTriangleFilled />
            </el-icon>
          </div>
        </el-tooltip>
        <UniverseTypeIcon :id="item.id" />
        {{ item.name }}
        <el-tag>{{ item.quantity }}</el-tag>
        <el-tag type="danger">{{ NumberUtils.readableText(getItemPrice(item)) }}</el-tag>
      </div>
    </el-card>
    <el-divider />
    <div class="flex flex-col space-y-1">
      <div v-for="resource in distributeResources" :key="resource.planet_id" class="flex space-x-2">
        <span class="flex">
          <UniverseTypeIcon :id="resource.type.id" />
          <span>{{ resource.name }}</span>
        </span>

        <span class="flex space-x-2">
          <span v-for="material in resource.material" :key="material.id">
            <el-tooltip :content="material.name">
              <el-tag>
                <div class="flex items-center">
                  <UniverseTypeIcon :id="material.id" /> {{ material.productQuantity }}
                </div>
              </el-tag>
            </el-tooltip>
          </span>
        </span>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss"></style>
